#include "app.h"
#include "module.h"
#include "kernel.h"
#include "scidriver.h"
#include "sci.h"
#include <string.h>


enum FrameAddr
{
	cFrmHeadAddr   = 0,		// 帧头所在地址
	cFrmDvcAddr    = 1,		// 设备所在地址
	cFrmLengthAddr = 2,		// 帧长度所在地址
	cFrmDataAddr   = 3
};

enum  ComBoard
{
    MainBrd = 0,	// 主板
    MainBtnPnl,		// 主按键板
   	SecBtnPnl		// 副按键板
};

#define cSciTime1S 		10 // sci 定时任务为100ms
#define cSciTime5S 		(5*cSciTime1S)
#define cSciTime10S 	(10*cSciTime1S)
#define cSciTime15S 	(15*cSciTime1S)
#define cSciTime30S 	(30*cSciTime1S)

#define cBuzSetMode1S	10
#define cBuzSetMode2S	20
#define cBuzSetMode5S	50


enum  cBtnSetCnt
{
	cBtnSetCntTrig       = 1,			// 按键一下
    cBtnSetCntPend       = cSciTime5S,	// 设置待定 5S
    cBtnSetCntLmtPstManu = cSciTime10S,	// 极限位置手动设置 10S
   	cBtnSetCntLmtPstAuto = cSciTime15S,	// 极限位置自动设置 15S
   	cBtnSetCntMax        = cSciTime30S	// 按键计数限制
};


INT16U uwSetStatus = cSetIdle;
INT16U ubWaterSetSts = cWaterSetDisinf;


INT16U uwCupSetBuzCnt;
INT16U uwWaterSetBuzCnt;

INT32U udwSetP1_Seat;
INT32U udwSetP1_StBk;
INT32U udwSetP2_Seat;
INT32U udwSetP2_StBk;
INT32U udwSetP3_Seat;
INT32U udwSetP3_StBk;

INT32U udwSetUpLmtSeat; // 最大极限Seat
INT32U udwSetDnLmtSeat; // 最小极限Seat
INT32U udwSetUpLmtStBk; // 最大极限StBk
INT32U udwSetDnLmtStBk; // 最小极限StBk

INT16U uwSpiteSts; // 多功能状态，吐痰


void sRcvSciProcess(INT8U sciid);
void sBtnLedSend(INT8U sciid);
void sWashSetBuzLedCtr(void);
void sWashCaseProcess(void);
void sSplitFucCancel(void);
void sMainBrdMsgProcess(INT8U sciid);



// CRC-8/MAXIM (多项式: 0x31)
INT8U calculate_crc8(INT8U *ubdata, INT8U length) 
{
	INT8U crc = 0x00;
	INT8U poly = 0x31;  // x^8 + x^5 + x^4 + 1
	INT8U i;
	INT8U j;

	for(i = 0; i < length; i++) 
	{
		crc ^= ubdata[i];
	    for(j = 0; j < 8; j++) 
		{
			if(crc & 0x80)
			{
				crc = (crc << 1) ^ poly;
			} 
			else 
			{
				crc <<= 1;
			}
	    }
	}
	return crc;
}


void sFrameheadChk(INT8U sciid)
{
	if(*pbCommandIn[sciid] == 0xAA)
	{
		ubSciRcvSts[sciid] = cFrameVersion;
		ubCommandLength[sciid] ++;
		pbCommandIn[sciid] ++;
	}
	else
	{
		pbCommandIn[sciid] = ubCommandBuffer[sciid];   
		ubCommandLength[sciid] = 0;
	}
}

/******************************************************************************/
//Function name : sFrameVersion
//Description   : 记录帧版本号
//
//Parameters    : None
//Return        : 
/******************************************************************************/
void sFrameVersion(INT8U sciid)
{
	ubFrameVerion[sciid] = *pbCommandIn[sciid];
	ubSciRcvSts[sciid] = cFrameLength;
	ubCommandLength[sciid] ++;
	pbCommandIn[sciid] ++;
}

void sFramelengthGet(INT8U sciid)
{
	if(*pbCommandIn[sciid] <= MAX_COMMAND_LENGTH) // 
	{
		ubSciRcvSts[sciid] = cFrameData;
		uwFrameLenth[sciid] = *pbCommandIn[sciid];
		ubCommandLength[sciid] ++;
		pbCommandIn[sciid] ++;
	}
	else
	{
		pbCommandIn[sciid] = ubCommandBuffer[sciid];   
		ubCommandLength[sciid] = 0;
		ubSciRcvSts[sciid] = cFramehead;
	}
}


void sFrameData(INT8U sciid)
{	
	uwFrameLenth[sciid]--;
	if(uwFrameLenth[sciid] == 0)
	{
		ubSciRcvSts[sciid] = cFrameCrc;
	}
	ubCommandLength[sciid] ++;
	pbCommandIn[sciid] ++;
}


/******************************************************************************/
//Function name : sFrameCrcChk
//Description   : CRC校验帧数据
//                1 如果校验成功
//                  程控器，则需要读取挑选与本身设备相关数据，且下发到非程控器的设备
//                  非程控器，则需要上传数据到程控器设备
//                2 校验不成功，退出
//Parameters    : None
//Return        : 
/******************************************************************************/
void sFrameCrcChk(INT8U sciid)
{	
	INT8U ubStrLen = 0;
	INT8U *strCrc;
	INT8U ubCrcChkRec;

	ubCrcChkRec = *pbCommandIn[sciid];
	ubStrLen = ubCommandBuffer[sciid][cFrmLengthAddr];
	strCrc   = &ubCommandBuffer[sciid][cFrmDataAddr];	// crc起始地址
	
	if(calculate_crc8(strCrc, ubStrLen) == ubCrcChkRec)	
	{	
		if(sciid == ComMainBrd)	// 如果是程控器发送数据
		{
			sMainBrdMsgProcess(sciid); // 程控器消息处理
		}
		else // 其他设备
		{
			
		}
		
		strCrc   = &ubCommandBuffer[sciid][cFrmDataAddr];
		BtnMatrix1[sciid].Byte = *strCrc++;
		BtnMatrix2[sciid].Byte = *strCrc++;
		BtnMatrix3[sciid].Byte = *strCrc;

	}

	pbCommandIn[sciid] = ubCommandBuffer[sciid];   
	ubCommandLength[sciid] = 0;
	ubSciRcvSts[sciid] = cFramehead;
}




/******************************************************************************/
//Function name : sSideBoxParseMsg
//Description   : 解析数据，控制
//                
//                  
//Parameters    : sciid: 程控器编号
//Return        : 
/******************************************************************************/
void sSideBoxParseMsg(INT8U sciid)
{	
	MainBrdData.CtrLed1.Bits.A = 1;

}



/******************************************************************************/
//Function name : sMainBrdMsgProcess
//Description   : 程控器消息处理
//                1 收到程控器的消息后，需要对程控器数暂存 
//                2 解析程控器信息，根据信息，控制本身设备
//                  这里注意，只有收到程控器的信息后，才能控制本身设备
//Parameters    : sciid: 程控器编号
//Return        : 
/******************************************************************************/
void sMainBrdMsgProcess(INT8U sciid)
{	
	INT8U ubStrLen = 0; 
	INT8U *strSrcdata;
	INT8U *strDstdata;

	ubStrLen = ubCommandBuffer[sciid][cFrmLengthAddr];	// 数据长度
	ubTransferLength[sciid] = ubStrLen;
	strSrcdata  = &ubCommandBuffer[sciid][cFrmDataAddr];// 数据起始位置
	strDstdata = ubTransferData[sciid];

	memcpy(strDstdata,strSrcdata,ubStrLen);
	// 解析数据，控制本设备数据
	sSideBoxParseMsg(sciid);

	

}





void sRcvSciProcess(INT8U sciid)
{
	INT8U ubSciTemp;

	while(1)
	{
		ubSciTemp = sSciRead(sciid,pbCommandIn[sciid]);  //receive data
			
		if(ubSciTemp == cSciRxBufEmpty)
		{
			return;
		}

		if(ubCommandLength[sciid] >= MAX_COMMAND_LENGTH)
		{
			pbCommandIn[sciid] = ubCommandBuffer[sciid];   
			ubCommandLength[sciid] = 0;
			ubSciRcvSts[sciid] = cFramehead;
		}
		else
		{
			uwFrameBrkCnt[sciid] = 0;
			switch(ubSciRcvSts[sciid])
			{
				case cFramehead:
					sFrameheadChk(sciid);
				break;
				case cFrameVersion:
					sFrameVersion(sciid);
				break;
				case cFrameLength:
					sFramelengthGet(sciid);
				break;
				case cFrameData:
					sFrameData(sciid);
				break;
				case cFrameCrc:
					sFrameCrcChk(sciid);
				break;			

				default:
					pbCommandIn[sciid] = ubCommandBuffer[sciid];   
					ubCommandLength[sciid] = 0;
					ubSciRcvSts[sciid] = cFramehead;
				break;

			}
		}
	}
}








void sPosKeyCancel(void) // 位置控制功能取消
{
	if((uwMotorCtrMode >= cMotorResetMode)  && (uwMotorCtrMode <= cMotorP3Mode))
	{
		uwMotorCtrMode = cMotorNormal;
	}
}










void sLogicProcess(void)
{
	// 触发式按键
	


	// 连续性按键
	

	// 设置键

	// 其他按键逻辑

	
}





void sBtnLedSend(INT8U sciid)
{
	INT8U ubStrLen = 0;
	INT8U *strCrc;
	INT8U ubDevice;
	static INT8U ubBtnLedSendCnt = 0;

	switch (sciid)
	{
		case ComDevice1:
			ubDevice = MainBtnPnl;
			break;
		case ComMainBrd:
			ubDevice = SecBtnPnl;
			break;
		default:
			break;
	}
		
	if((sBtnLedCheck(sciid) == 1) || (ubBtnLedSendCnt++ >= 2))
	{
		ubBtnLedSendCnt = 0;
	
		ubUserDataBuf[sciid][ubStrLen++] = 0xAA; 		// 帧头
		ubUserDataBuf[sciid][ubStrLen++] = ubDevice;	// 通讯位置
		ubUserDataBuf[sciid][ubStrLen++] = 6; 			// 通讯长度
		strCrc = &ubUserDataBuf[sciid][ubStrLen];		// crc起始地址

		ubUserDataBuf[sciid][ubStrLen++] = LedMatrix1[sciid].Byte;
		ubUserDataBuf[sciid][ubStrLen++] = LedMatrix2[sciid].Byte;
		ubUserDataBuf[sciid][ubStrLen++] = 0;
		ubUserDataBuf[sciid][ubStrLen++] = 0;		// 兼容更多按键或命令
		ubUserDataBuf[sciid][ubStrLen++] = 0;
		ubUserDataBuf[sciid][ubStrLen++] = 0;
		ubUserDataBuf[sciid][ubStrLen++] = calculate_crc8(strCrc, 6); // CRC校验	

		sSciWrite(sciid,&ubUserDataBuf[sciid][0],ubStrLen);
	}

	
	

}


void sWashSetBuzLedCtr(void)
{
	switch(udwWashSetCase)
	{
		case 1:
			sBuzOnce();
			mLedSet(1,4,2);
			break;
		case 2:
			sBuzTwice();
			mLedSet(2,4,2);
			break;
		case 3:
			sBuzThird();
			mLedSet(3,4,2);
			break;
		case 4:
			sBuzfour();
			mLedSet(4,4,2);
			break;
		default:
			
			break;	
	}
	

}


void sWashCaseProcess(void)
{
	switch(udwWashSetCase)
	{
		case 1:
			MemPlace.WashCase = cWaterTimeCase1;
			break;
		case 2:
			MemPlace.WashCase = cWaterTimeCase2;
			break;
		case 3:
			MemPlace.WashCase = cWaterTimeCase3;
			break;
		case 4:
			MemPlace.WashCase = cWaterTimeCase4;
			break;
		default:
			MemPlace.WashCase = cWaterTimeDefault;
			break;
	}
}


/******************************************************************************/
//Function name : sSplitFucCancel
//Description   : 吐痰功能取消
//                
//Parameters    : None
//Return        : None
/******************************************************************************/
void sSplitFucCancel(void)
{
	if(uwSpiteSts != cSpiteInit)
	{
		uwSpiteSts = cSpiteInit;
		mLpLedOff();
		SysSts1.Bits.Water = cWaterRunInit; // 冲盂关闭
		if(uwMotorCtrMode == cMotorSpiteMode)
		{
			uwMotorCtrMode = cMotorNormal;
		}
	}
}



